package com.learning.spring.optimize.property.placeholder;

import com.google.common.collect.Lists;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.env.Environment;

import java.util.List;

/**
 * ClassName: PropertyPlaceholderConfigurer
 * Description: 使用外部属性文件
 * Date: 2018/8/7 16:01 【需求编号】
 *
 * @author Sam Sho
 * @version V1.0.0
 */
public class PropertyConfigurer {

    public static void main(String[] args) {
        test2();
    }

    /**
     * 使用外部属性文件：
     * 方式1：配置文件加载至spring上下文中，然后通过 ${} 或者 @Value("${jdbc.type}") 取得值
     * 1、PropertyPlaceholderConfigurer 类实现，实现了 BeanFactoryPostProcessor ，也是一个工厂后置处理器
     * 2、PropertySourcesPlaceholderConfigurer，更加建议使用：就像 <context:property-placeholder> 使用的那样
     * 3、<context:property-placeholder> 配置
     * 4、注解：@PropertySource(value = "classpath:spring.properties") 结合 PropertySourcesPlaceholderConfigurer 的 bean
     * <p>
     * 方式2：调用bean属性的方式实现，调用Bean 的属性值 #{bean.XXX} 或者 @Value("#{configReader['jdbc.type']}") 获取
     * 1、PropertiesFactoryBean 类实现
     * 2、<util:properties id="configReader" location="classpath:jdbc.properties" scope="singleton"/> 配置实现，更加推荐
     */
    static void test() {

    }

    /**
     * 加载至spring上下文中实现
     * xml 中 使用 ${jdbc.username}
     * 注解或者 Javaconfig 中 使用 @Value("${jdbc.type}")
     */
    static void test2() {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");
        PropertyConfig propertyConfig = context.getBean(PropertyConfig.class);
        System.out.println(propertyConfig.getName());
        System.out.println(propertyConfig.getType());
    }

    /**
     * 调用bean属性的方式实现
     */
    static void test3() {

    }

    /**
     * 给文件加密，使用连接池实现更好（如 druid 自带加解密功能）
     */
    static void test4() {

    }
}

@Setter
@Getter
@Configuration
class PropertyConfig {

    @Autowired
    Environment environment;

    private String name;

    @Value("${jdbc.type}")
    private String type;

    /**
     * 注入操作系统信息
     */
    @Value("#{systemProperties['os.name']}")
    private String osName;

    public String getName() {
        return environment.getProperty("name");
    }
}

/**
 * 自定义解密
 */
class CustomProperties extends PropertySourcesPlaceholderConfigurer {

    private List<String> list = Lists.newArrayList("userName", "pwd");

    @Override
    protected String convertProperty(String propertyName, String propertyValue) {
        // 判断属性是否是需要加密的
        if (list.contains(propertyName)) {
            return this.convertPropertyValue(propertyValue);
        }
        return propertyValue;
    }

    @Override
    protected String convertPropertyValue(String originalValue) {
        // 属性解密，略
        return originalValue;
    }
}
